home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_gnome-pilot.idb / usr / freeware / share / gob / gnome-pilot-conduit-management.gob.z / gnome-pilot-conduit-management.gob
Text File  |  2001-10-09  |  18KB  |  651 lines

  1. /* gnome-pilot-conduit-management.gob
  2.  *
  3.  * Copyright (C) 1999-2000  Free Software Foundation
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the
  17.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  18.  * Boston, MA 02111-1307, USA.
  19.  *
  20.  * Authors: Eskil Heyn Olsen <eskil@eazel.com>
  21.  */
  22.  
  23. /* GOB version requirement */
  24. requires 0.92.4
  25.  
  26. /*
  27.   Design notes :
  28.  
  29.   Data containment will be split into two ;
  30.  
  31.   1) The GnomePilotConduitManagement object, which is the one users
  32.      will access. Through this, they can query attributes and 
  33.      instantiate the conduit.
  34.      This will also carry all non-static info 
  35.      (ie. info not found in the .conduit files)
  36.  
  37.   2) GnomePilotConduitMgmtData structs, which are the internally kept
  38.      structures containing what was read from the .conduit files.
  39.  */
  40.  
  41. %h{
  42. #include <glib.h>
  43. #include <gtk/gtkobject.h>
  44. #include <gpilotd/gnome-pilot-conduit.h>
  45. #include <gmodule.h>
  46.  
  47. #ifdef DLOPEN_TEST
  48. #include <dlfcn.h>
  49. #endif
  50.  
  51. enum GnomePilotConduitMgmtError {
  52.     GNOME_PILOT_CONDUIT_MGMT_OK,
  53.     GNOME_PILOT_CONDUIT_MGMT_ALREADY_LIVE,
  54.     GNOME_PILOT_CONDUIT_MGMT_ERROR,
  55.     GNOME_PILOT_CONDUIT_MGMT_FATAL
  56. };
  57.  
  58. enum GnomePilotConduitType {
  59.     GNOME_PILOT_CONDUIT_TYPE_SHLIB,
  60. };
  61.  
  62. enum GnomePilotConduitFilter {
  63.     GNOME_PILOT_CONDUIT_MGMT_ID=0,
  64.     GNOME_PILOT_CONDUIT_MGMT_NAME
  65. };
  66.  
  67. typedef struct _GnomePilotConduitMgmtData GnomePilotConduitMgmtData;
  68. struct _GnomePilotConduitMgmtData {
  69.     /* The id of the conduit */
  70.     gchar *id;
  71.     /* The locale name of the conduit */
  72.     gchar *name;
  73.     /* The type of the conduit, sharedlib or whatgives */
  74.     enum GnomePilotConduitType type;
  75.     /* Where the conduit cab be found */
  76.     gchar *location;
  77.     /* A hash of all attributes of type string, note
  78.        the local translation overwrites others. */
  79.     GHashTable *string_attributes;
  80. };
  81. %}
  82.  
  83. %{
  84. #include <config.h>
  85. #include <sys/types.h>
  86. #include <sys/stat.h>
  87. #include <dirent.h>
  88. #include <unistd.h>
  89. #include <gnome-xml/tree.h>
  90. #include <gnome-xml/parser.h>
  91.  
  92. /* 
  93.    MT-Level :
  94.    Change these defines to make the lib MT safe. 
  95.    (UN)LOCK_MY_HASHES should mutex the conduitname_to_datastruct hash
  96.    (UN)LOCK_MY_COUNTER should mutex the number_of_instances counter
  97.    (UN)LOCK_INSTANCE should mutex the current Gnome:Pilot:Conduit:Management instance
  98.    uhm, don't think I'll use LOCK_INSTANCE
  99. */
  100. #define LOCK_MY_COUNTER
  101. #define UNLOCK_MY_COUNTER
  102.  
  103. #define LOCK_MY_HASHES
  104. #define UNLOCK_MY_HASHES
  105.  
  106. #define LOCK_INSTANCE
  107. #define UNLOCK_INSTANCE
  108.  
  109.   /* the version that the conduit xml spec files should have */
  110. #define CONDUIT_XML_VERSION "1.0"
  111.  
  112. gboolean initialized = FALSE;
  113. int number_of_instances  = 0;
  114. GHashTable *conduitname_to_datastruct; 
  115. GHashTable *conduitid_to_datastruct; 
  116.  
  117. /* these are the list of valid tags in addition to conduit-attribute */
  118. static const gchar *valid_tags[] = {"conduit","name",NULL};
  119. %}
  120.  
  121. class Gnome:Pilot:Conduit:Management from Gtk:Object {
  122.     /* TRUE if the module is loaded can be used for sync. */
  123.     private gboolean loaded;
  124.  
  125.     /* if loaded==TRUE, this is the GModule handler */
  126.     private GModule *dlhandle;
  127.     
  128.     /* if loaded==TRUE, these are the load/destroy funcs
  129.        loaded from the object */
  130.     private GnomePilotConduitLoadFunc load_func;
  131.     private GnomePilotConduitDestroyFunc destroy_func;
  132.  
  133.     /* This is a pointer to a MgmtData object returned from
  134.        conduitname_to_datastruct or conduitid_to_datastruct hashes */
  135.     private GnomePilotConduitMgmtData *mgmtdata;
  136.  
  137.  
  138.     /***************************/
  139.     /* Initialization          */
  140.     /***************************/
  141.  
  142.     /* This reads the .conduit files and loads the hashes */
  143.     private void 
  144.     initializer(void) {
  145.         if (!initialized) {
  146.             struct dirent **namelist;
  147.             int dirs;
  148.             g_message("reading .conduit's from %s",CONDUITDIR);
  149.             /* Do read of all .conduit files here */
  150.             LOCK_MY_HASHES;
  151.             conduitname_to_datastruct  = g_hash_table_new(g_str_hash,g_str_equal);
  152.             conduitid_to_datastruct  = g_hash_table_new(g_str_hash,g_str_equal);
  153.             dirs = scandir(CONDUITDIR,
  154.                        &namelist,
  155.                        (int (*)(const struct dirent*))gnome_pilot_conduit_management_select_dir_entry,
  156.                        alphasort);
  157.             /* g_message("direntries = %d",dirs); */
  158.             for (; dirs>0;dirs--) {
  159.                 GnomePilotConduitMgmtData *conduitdata;
  160.                 conduitdata = read_conduit_xml(namelist[dirs-1]->d_name);
  161.             }
  162.             UNLOCK_MY_HASHES;
  163.         }
  164.         initialized = TRUE;
  165.     }
  166.  
  167.     /* This loads a conduit of a specific type */
  168.     public GnomePilotConduitManagement*
  169.     new(gchar *_name (check null), enum GnomePilotConduitFilter filter) 
  170.         onerror NULL
  171.     {
  172.         GtkObject *ret = NULL;
  173.         GHashTable *which_to_use = NULL;
  174.         GnomePilotConduitManagement *obj  = NULL;
  175.         GnomePilotConduitMgmtData *_mgmtdata = NULL;
  176.  
  177.         LOCK_MY_COUNTER;
  178.         if (number_of_instances==0) {
  179.             gnome_pilot_conduit_management_initializer();
  180.         }
  181.         number_of_instances++;
  182.         UNLOCK_MY_COUNTER;
  183.         
  184.         switch (filter) {
  185.         case GNOME_PILOT_CONDUIT_MGMT_ID:
  186.             which_to_use = conduitid_to_datastruct;
  187.             break;
  188.         case GNOME_PILOT_CONDUIT_MGMT_NAME:
  189.             which_to_use = conduitname_to_datastruct;
  190.             break;
  191.         }
  192.  
  193.         _mgmtdata = g_hash_table_lookup(which_to_use,_name);
  194.         if (_mgmtdata) {
  195.             ret = GTK_OBJECT(GET_NEW);
  196.             obj = SELF(ret);
  197.             obj->_priv->loaded = FALSE;
  198.             obj->_priv->mgmtdata = _mgmtdata;
  199.         } else {
  200.             g_warning("Unknown conduit, name=\"%s\"",_name);
  201.         }
  202.  
  203.         return obj;
  204.     }
  205.     
  206.     /* Destroys this instance of self 
  207.        FIXME: dealloc all the loaded !!
  208.      */
  209.         public void
  210.     destroy(self) {
  211.         LOCK_INSTANCE;
  212.         LOCK_MY_COUNTER;
  213.         number_of_instances--;
  214.         if (number_of_instances==0) {
  215.             /* g_message("No more instances"); */
  216.         }
  217.         gtk_object_destroy(GTK_OBJECT(self));
  218.         UNLOCK_MY_COUNTER;
  219.         UNLOCK_INSTANCE;
  220.     }
  221.  
  222.     /***************************/
  223.     /*      XML LOADING        */
  224.     /***************************/
  225.     
  226.     /* Used for scandir, checks that entry ends in .conduit 
  227.      and is not a dir. */
  228.     private int
  229.     select_dir_entry(struct dirent *de) {
  230.         gchar *ptr;
  231.         struct stat st;
  232.         if (de==NULL || de->d_name==NULL) return 0;
  233.         /* g_message("select_dir_entry(%s)",de->d_name); */
  234.         if (strlen(de->d_name) < strlen(".conduit")) return 0;
  235.         ptr = de->d_name;
  236.         ptr += strlen(de->d_name) - strlen(".conduit");
  237.         if (strcmp(ptr,".conduit")) return 0;
  238.         ptr = g_strdup_printf("%s%s",CONDUITDIR,de->d_name);
  239.         stat(ptr,&st);
  240.         if (S_ISDIR(st.st_mode) || 
  241.             S_ISCHR(st.st_mode) || 
  242.             S_ISFIFO(st.st_mode) || 
  243.             S_ISSOCK(st.st_mode)) return 0;
  244.         g_message("select_dir_entry(%s)",de->d_name);
  245.         return 1;
  246.     }
  247.  
  248.     /* Checks wether a tag is in the valid_tags list */
  249.     private gboolean 
  250.     is_other_valid_tag(const gchar *s) {
  251.         gint i = 0;
  252.         for (i=0;valid_tags[i];i++)
  253.             if (g_strcasecmp(s,valid_tags[i])==0) return TRUE;
  254.         return FALSE;
  255.         
  256.     }
  257.     /*  This reads the XML header, and creates a new
  258.         GnomePilotConduitMgmt if ok, otherwise returns NULL */
  259.     private GnomePilotConduitMgmtData*
  260.     check_xml_version(xmlNodePtr root) {
  261.         GnomePilotConduitMgmtData *ret;
  262.         xmlChar *version;
  263.         
  264.         version = xmlGetProp(root,"version");
  265.         /* g_message("version = %s",version); */
  266.         if (version==NULL || g_strcasecmp(version,CONDUIT_XML_VERSION)!=0) {
  267.             g_warning("incompatible version");
  268.             return NULL;    
  269.         }
  270.         /* g_message("XML version is ok, creating entry"); */
  271.         ret = g_new(GnomePilotConduitMgmtData,1);
  272.         ret->string_attributes = g_hash_table_new(g_str_hash,g_str_equal);
  273.         return ret;
  274.     }
  275.  
  276.     /* This loads the <conduit type=... location=...> stuff */
  277.     private gboolean
  278.     read_conduit_topdata(GnomePilotConduitMgmtData *obj, xmlNodePtr root) {
  279.         xmlNodePtr node;
  280.         xmlChar *type,*location,*id_string;
  281.  
  282.         node = root->childs;
  283.         /* until we find the "conduit" node */
  284.         while (node && g_strcasecmp(node->name,"conduit")!=0) {
  285.             node = node->next;
  286.         }
  287.         if (!node) {
  288.             g_warning("error in XML, missing the \"conduit\" node");
  289.             return FALSE;
  290.         }
  291.         type = xmlGetProp(node,"type");
  292.         location = xmlGetProp(node,"location");
  293.         id_string = xmlGetProp(node,"id");
  294.  
  295.         if (id_string==NULL) {
  296.             g_warning("error in XML, missing id_string");
  297.             return FALSE;
  298.         } else {
  299.             if (strchr(id_string,' ')) {
  300.                 g_warning("error in XML, id_string bad");
  301.                 return FALSE;
  302.             }
  303.         }
  304.         if (location==NULL) {
  305.             g_warning("error in XML, missing location");
  306.             return FALSE;
  307.         }
  308.  
  309.         if(g_strcasecmp(type,"shlib")==0) {
  310.             obj->type = GNOME_PILOT_CONDUIT_TYPE_SHLIB;
  311.         } else {
  312.             g_warning("Unknown conduit type");
  313.             return FALSE;    
  314.         }
  315.         obj->location = g_strdup(location);
  316.         obj->id = g_strdup(id_string);
  317.         g_hash_table_insert(conduitid_to_datastruct,
  318.                     obj->id,
  319.                     obj);
  320.         return TRUE;
  321.     }
  322.  
  323.     /* This loads the correct <name ...> tag, taking the correct i18n */
  324.     private gboolean
  325.     read_conduit_name(GnomePilotConduitMgmtData *obj, xmlNodePtr root) {
  326.         xmlNodePtr node;
  327.         xmlChar *value,*lang;
  328.         gchar *current_name=NULL;
  329.  
  330.         node = root->childs;
  331.         /* until we find a name node */
  332.         while (node) {
  333.             while (node && g_strcasecmp(node->name,"name")) {
  334.                 node = node->next;
  335.             }
  336.             if (node) {
  337.                 value = xmlGetProp(node,"value");
  338.                 lang = xmlGetProp(node,"lang");
  339.                 /* if this is a default name, and there
  340.                    is no current_name, set it. If on the
  341.                    other hand there is a lang, and it's the current, set it*/
  342.                 if ((!lang && !current_name) ||
  343.                     (lang && gnome_i18n_get_language() && g_strcasecmp(lang,gnome_i18n_get_language())==0)) {
  344.                     if (current_name) g_free(current_name);
  345.                     current_name = g_strdup(value);
  346.                 }
  347.                 node = node->next;
  348.             }
  349.         }
  350.         if (!current_name) {
  351.             g_warning("could not determine name from XML");
  352.             return FALSE;
  353.         }
  354.  
  355.         obj->name = g_strdup(current_name);
  356.         g_hash_table_insert(conduitname_to_datastruct,
  357.                     obj->name,
  358.                     obj);
  359.         return TRUE;
  360.     }
  361.  
  362.     /* When this is called, HASHES should be locked */
  363.     /* Reads the attributes from the XML file */
  364.     private void
  365.     read_conduit_attributes(GnomePilotConduitMgmtData *obj, xmlNodePtr root) {
  366.         xmlNodePtr node;
  367.  
  368.         /* loop over the children */
  369.         for (node = root->childs; node!=NULL; node=node->next) {
  370.             if (g_strcasecmp(node->name,"conduit-attribute")==0) {
  371.                 xmlChar *lang,*name,*type,*value;
  372.                 gchar *attr_with_lang;
  373.                 
  374.                 lang = xmlGetProp(node,"lang");
  375.                 name = xmlGetProp(node,"name");
  376.                 type = xmlGetProp(node,"type");
  377.                 value = xmlGetProp(node,"value");
  378.  
  379.                 if (value==NULL) {
  380.                     g_warning("attribute has no value");
  381.                     continue;
  382.                 }
  383.                 if (name==NULL) {
  384.                     g_warning("attribute has no name");
  385.                     continue;
  386.                 }
  387.  
  388.                 /* g_message("conduit-attribute [%s-%s] is \"%s\"/%s",
  389.                   name,lang,value,type); */
  390.                 if (lang) {
  391.                     attr_with_lang = g_strdup_printf("%s##%s",
  392.                                      lang,name);
  393.                 } else {
  394.                     attr_with_lang = g_strdup(name);
  395.                 }
  396.                 /* if no type, assume string */
  397.                 if(type==NULL || g_strcasecmp(type,"string")==0) {
  398.                     g_hash_table_insert(obj->string_attributes,
  399.                                 attr_with_lang,
  400.                                 g_strdup(value));
  401.                 } else {
  402.                     g_warning("Unknown type %s",type);
  403.                 }
  404.                 
  405.             } else if (!is_other_valid_tag(node->name)) { 
  406.                 g_warning("node->name = \"%s\", unhandled ",node->name);
  407.             } 
  408.         } 
  409.     }
  410.  
  411.     /* When this is called, HASHES should be locked */
  412.     /* Open and checks the xml file */
  413.     private GnomePilotConduitMgmtData*
  414.     read_conduit_xml(gchar *fname) {
  415.         gchar *name;
  416.         xmlDocPtr doc;
  417.         xmlNodePtr root;
  418.         GnomePilotConduitMgmtData *ret;
  419.         
  420.         name = g_strdup_printf("%s%s",CONDUITDIR,fname);
  421.         /* g_message("read_conduit_xml: reading from %s",name); */
  422.         
  423.         /* load the thing */
  424.         doc = xmlParseFile(name);
  425.         
  426.         /* check validity 1 */
  427.         if(!doc->root ||
  428.            !doc->root->name ||
  429.            g_strcasecmp(doc->root->name,"gnome-pilot-conduit")!=0) {
  430.             xmlFreeDoc(doc);
  431.             return NULL;
  432.         }      
  433.         
  434.         root = doc->root;
  435.         ret = check_xml_version(root);
  436.         if (!read_conduit_topdata(ret,root) ||
  437.             !read_conduit_name(ret,root)) {
  438.             g_hash_table_destroy(ret->string_attributes);
  439.             g_free(ret);
  440.             xmlFreeDoc(doc);
  441.             return NULL;
  442.         }
  443.         ;
  444.         read_conduit_attributes(ret,root);
  445.  
  446.         xmlFreeDoc(doc);
  447.         return ret;
  448.     }
  449.  
  450.  
  451.     /***************************/
  452.     /* ATTRIBUTE QUERYING      */
  453.     /***************************/
  454.  
  455.     /* returns the local name of the conduit */
  456.     public const gchar*
  457.     get_name(self) {
  458.         return self->_priv->mgmtdata->name;
  459.     }
  460.  
  461.     /* returns the id of the conduit */
  462.     public const gchar*
  463.     get_id(self) {
  464.         return self->_priv->mgmtdata->id;
  465.     }
  466.  
  467.     /* this takes a name and the data, appends the name to the output */
  468.     private void
  469.     hfunc_build_name_list(gchar *name, GnomePilotConduitMgmtData *data, GList **output) {
  470.         (*output) = g_list_append(*output,name);
  471.     }
  472.  
  473.     public gint
  474.     get_conduits(GList **output (check null),enum GnomePilotConduitFilter filter) 
  475.         onerror GNOME_PILOT_CONDUIT_MGMT_ERROR
  476.         {
  477.         GHashTable *which_to_use = NULL;
  478.         gnome_pilot_conduit_management_initializer();
  479.         LOCK_MY_HASHES;
  480.         switch (filter) {
  481.         case GNOME_PILOT_CONDUIT_MGMT_ID:
  482.             which_to_use = conduitid_to_datastruct;
  483.             break;
  484.         case GNOME_PILOT_CONDUIT_MGMT_NAME:
  485.             which_to_use = conduitname_to_datastruct;
  486.             break;
  487.         }
  488.         g_hash_table_foreach(which_to_use,
  489.                      (GHFunc)hfunc_build_name_list,
  490.                      output);
  491.         UNLOCK_MY_HASHES;        
  492.         return GNOME_PILOT_CONDUIT_MGMT_OK;
  493.     }
  494.  
  495.  
  496.     /* used to retrieve all attribute keys */
  497.         private 
  498.     void attribs_foreach(gchar *key, gpointer unused, GList **l) {
  499.         (*l) = g_list_append(*l,key);
  500.     }
  501.  
  502.     /* used to retrieve all attribute keys without the lang code */
  503.         private 
  504.     void attribs_filter_lang_foreach(gchar *key, gpointer unused, GList **l) {
  505.         if (!strstr(key,"##"))
  506.             (*l) = g_list_append(*l,key);
  507.     }
  508.  
  509.     /* Returns all the available attributes 
  510.        who are on the form <name>[##<lang>]
  511.        if filter_lang = TRUE, the lang is removed
  512.      */
  513.     public GList*
  514.     get_attribute_list(self,gboolean filter_lang) {
  515.         GList *attribs = NULL;
  516.         LOCK_MY_HASHES;
  517.         
  518.         if (filter_lang) {
  519.             g_hash_table_foreach(self->_priv->mgmtdata->string_attributes,(GHFunc)attribs_filter_lang_foreach,&attribs);
  520.         } else {
  521.             g_hash_table_foreach(self->_priv->mgmtdata->string_attributes,(GHFunc)attribs_foreach,&attribs);
  522.         }
  523.         UNLOCK_MY_HASHES;
  524.         return attribs;
  525.     }
  526.  
  527.     /* Gets an attribute. Lang is the preferred language
  528.        for the attribute, NULL causes gnome_i18n_get_language() to be used */
  529.     public const gpointer*
  530.     get_attribute(self,
  531.               gchar *attribute_name (check null),
  532.               gchar *lang) 
  533.         onerror NULL 
  534.     {        
  535.         gpointer *attr = NULL;        
  536.         gchar *attribute_name_with_lang;
  537.         LOCK_MY_HASHES;
  538.         /* if no such conduit, do nothing and NULL will be returned */
  539.         if (strstr(attribute_name,"##")==NULL) {
  540.             attribute_name_with_lang = g_strdup_printf("%s##%s",
  541.                                    lang?lang:gnome_i18n_get_language(),
  542.                                    attribute_name);
  543.         } else {
  544.             attribute_name_with_lang = g_strdup(attribute_name);
  545.         }
  546.         attr = g_hash_table_lookup(self->_priv->mgmtdata->string_attributes,
  547.                        attribute_name_with_lang);
  548.         g_free(attribute_name_with_lang);
  549.         if (!attr) {
  550.             /* no luck, try without language */
  551.             attr = g_hash_table_lookup(self->_priv->mgmtdata->string_attributes,attribute_name);
  552.         }
  553.         UNLOCK_MY_HASHES;
  554.         return attr;
  555.     }
  556.  
  557.     /***************************/
  558.     /* CONDUIT ACTIVATION      */
  559.     /***************************/
  560.  
  561.     /* opener for shlib conduits
  562.        opens the conduit and loads the func, preparing it
  563.        for use */
  564.     private gint
  565.     shlib_loader(self) {
  566.         gchar *location = self->_priv->mgmtdata->location;
  567.         GModule *dlhandle = self->_priv->dlhandle;
  568.         if (g_module_supported()!=TRUE) {
  569.             g_warning(_("module loading not supported, fatal!"));
  570.             return GNOME_PILOT_CONDUIT_MGMT_FATAL;
  571.         }
  572.         if ((dlhandle = g_module_open(location,0))==NULL) {
  573.             g_warning("unable to g_module_open(%s), reason %s", location, g_module_error ());
  574. #ifdef DLOPEN_TEST
  575.             {
  576.                 void *handle;
  577.                 g_warning ("doing dlopen_test");
  578.                 handle = dlopen (location, RTLD_LAZY);
  579.                 if (handle == NULL) {
  580.                     g_message ("dlopen error is %s",dlerror());
  581.                 }
  582.                 dlclose (handle);
  583.             }
  584. #endif
  585.             return GNOME_PILOT_CONDUIT_MGMT_ERROR;
  586.         } 
  587.         if (g_module_symbol(dlhandle,"conduit_get_gpilot_conduit",
  588.                     (gpointer)&(self->_priv->load_func))==FALSE) {
  589.             g_warning("malformed conduit, cannot locate symbol"
  590.                   "\"conduit_get_gpilot_conduit\", error %s",
  591.                   g_module_error());
  592.             return GNOME_PILOT_CONDUIT_MGMT_ERROR;
  593.         }
  594.         if (g_module_symbol(dlhandle,"conduit_destroy_gpilot_conduit",
  595.                     (gpointer)&(self->_priv->destroy_func))==FALSE) {
  596.             g_warning("malformed conduit, cannot locate symbol"
  597.                   "\"conduit_destroy_gpilot_conduit\", error %s",
  598.                   g_module_error());
  599.             return GNOME_PILOT_CONDUIT_MGMT_ERROR;
  600.         }
  601.         self->_priv->loaded = TRUE;
  602.         return GNOME_PILOT_CONDUIT_MGMT_OK;
  603.     }
  604.  
  605.     /* Loads the conduit and creates an instance for
  606.        the specified pilot 
  607.        Returns 
  608.     */
  609.     public gint
  610.     instantiate_conduit(self, guint pilot_id, GnomePilotConduit **instance (check null)) 
  611.         onerror GNOME_PILOT_CONDUIT_MGMT_ERROR 
  612.     {
  613.         gint err = GNOME_PILOT_CONDUIT_MGMT_OK;
  614.         (*instance) = NULL;
  615.         LOCK_INSTANCE;
  616.         if (self->_priv->loaded==FALSE) {
  617.             switch(self->_priv->mgmtdata->type) {
  618.             case GNOME_PILOT_CONDUIT_TYPE_SHLIB: 
  619.                 err = shlib_loader(self);
  620.                 break;
  621.             default:
  622.                 g_warning("unknown conduit type");
  623.                 break;
  624.             }
  625.         }
  626.         if (err == GNOME_PILOT_CONDUIT_MGMT_OK) {
  627.             (*instance) = self->_priv->load_func(pilot_id);
  628.         }
  629.         UNLOCK_INSTANCE;
  630.         return err;
  631.     }
  632.  
  633.     /* Destroys the conduit instance */
  634.         public gint
  635.     destroy_conduit(self, GnomePilotConduit **instance (check null)) 
  636.                         onerror GNOME_PILOT_CONDUIT_MGMT_ERROR 
  637.     {
  638.         LOCK_INSTANCE;
  639.         if (self->_priv->loaded==TRUE) {
  640.             self->_priv->destroy_func(*instance);
  641.         }
  642.         UNLOCK_INSTANCE;
  643.         return GNOME_PILOT_CONDUIT_MGMT_OK;
  644.     }
  645. }
  646.  
  647. %{
  648.  
  649. %}
  650.  
  651.